<?php
class UserModel {
	private $_aFilter = array ();
	private $_sSortName = 'use_name';
	private $_sSortType = 'asc';
	private $_aStatus = array ('active' => '正常', 'close' => '关闭' );
	private $_aAuth = array ();
	
	public function login($sName, $sPassword) {
		$aInfo = self::get ( $sName, false );
		if (! $aInfo) {
			return - 1;
		} else {
			if ($aInfo ['password'] != self::_str2password ( $sPassword )) {
				return - 2;
			} elseif ($aInfo ['status'] != 'active') {
				return - 3;
			} else {
				$sSql = 'UPDATE users SET use_last_login_time = ?, use_last_login_ip = ? WHERE use_id = ?';
				Base::$oBase->Db_exec ( $sSql, array (time (), Base::$oBase->Net_getIp ( null, 'long' ), $aInfo ['id'] ) );
				$_SESSION ['user'] = $aInfo;
				return $aInfo ['id'];
			}
		}
	}
	
	public function get($iUId, $bIsId = true) {
		$oCache = Base::loadClass ( 'Cache' );
		if ($bIsId) {
			$aData = $oCache->get ( $iUId, 'user' );
		}
		if ($aData == '__NOCACHE__' || $bIsId == false) {
			if ($bIsId) {
				$aData = Base::$oBase->Db_get ( 'users', array ('id' => $iUId ) );
			} else {
				$aData = Base::$oBase->Db_get ( 'users', array ('name' => $iUId ) );
			}
			if (is_array ( $aData )) {
				$aData ['privilege'] = array ();
				$aData ['privilege_item'] = array ();
				$sSql = 'SELECT usp_pri_id id, pri_value `value` FROM user_privileges, privileges WHERE usp_use_id = ? AND usp_pri_id = pri_id';
				Base::$oBase->Db_query ( $sSql, $aData ['id'] );
				while ( ($aRow = Base::$oBase->Db_getRow ()) !== false ) {
					$aData ['privilege'] [$aRow ['id']] = $aRow ['value'];
					$aPrivilege = Base::$oBase->Privilege_get_model ( $aRow ['id'] );
					foreach ( $aPrivilege ['method'] as $sModel => $aMethod ) {
						if (array_key_exists ( $sModel, $aData ['privilege_item'] )) {
							$aData ['privilege_item'] [$sModel] = array_unique ( array_merge ( $aData ['privilege_item'] [$sModel], $aMethod ) );
						} else {
							$aData ['privilege_item'] [$sModel] = $aMethod;
						}
					}
				}
				$aData ['authorize'] = array ();
				$sSql = 'SELECT pri_id id, pri_value `value` FROM authorize, privileges WHERE aut_use_id = ? AND aut_pri_id = pri_id';
				Base::$oBase->Db_query ( $sSql, $aData ['id'] );
				while ( ($aRow = Base::$oBase->Db_getRow ()) !== false ) {
					$aData ['authorize'] [$aRow ['id']] = $aRow ['value'];
				}
			}
			$oCache->set ( $aData ['id'], $aData, 'user', 0 );
		}
		return $aData;
	}
	
	public function logout() {
		unset ( $_SESSION ['user'] );
	}
	
	public function checkIsLogin() {
		if (isset ( $_SESSION ['user'] )) {
			return true;
		} else {
			return false;
		}
	}
	
	public function checkAuth($sMethod, $iUserId = null) {
		if (isset ( $this->_aAuth [$sMethod] )) {
			return $this->_aAuth [$sMethod];
		}
		list ( $sAction, $sMethod ) = explode ( '::', $sMethod );
		if ($iUserId == null) {
			$iUserId = intval ( $_SESSION ['user'] ['id'] );
		}
		if ($iUserId > 0 && in_array ( $iUserId, preg_split ( '/[,\s]+/s', Base::getConf ( 'base.admin' ) ) )) {
			return true;
		}
		
		$sAction = ucfirst ( preg_replace ( '/Action$/', '', $sAction ) );
		$sAction = $sAction ? $sAction : 'Index';
		$sMethod = $sMethod ? $sMethod : 'index';
		$aNoAuth = Base::$oBase->Privilege_getNoAuth_model ();
		if (is_array ( $aNoAuth [$sAction] ) && (in_array ( '__FULL__', $aNoAuth [$sAction] ) || in_array ( $sMethod, $aNoAuth [$sAction] ))) {
			$this->_aAuth [$sMethod] = true;
			return true;
		}
		$aUserInfo = $this->get ( $iUserId );
		if (! is_array ( $aUserInfo ['privilege_item'] [$sAction] )) {
			$this->_aAuth [$sMethod] = false;
			return false;
		}
		if (in_array ( '__FULL__', $aUserInfo ['privilege_item'] [$sAction] )) {
			$this->_aAuth [$sMethod] = true;
			return true;
		}
		if (in_array ( $sMethod, $aUserInfo ['privilege_item'] [$sAction] )) {
			$this->_aAuth [$sMethod] = true;
			return true;
		} else {
			$this->_aAuth [$sMethod] = false;
			return false;
		}
	}
	
	public function checkIsSA($iUserId) {
		if (in_array ( $iUserId, preg_split ( '/[,\s]+/s', Base::getConf ( 'base.admin' ) ) )) {
			return true;
		} else {
			return false;
		}
	}
	
	private function _str2password($sString) {
		return md5 ( $sString . '_password' );
	}
	
	public function getList($iPage, $iLimit = 20) {
		$aWhere = array ('use_name <> ?' );
		$aValue = array ('root' );
		if (! array_key_exists ( 'status', $this->_aFilter )) {
			$this->_aFilter ['status'] = 'active';
		}
		foreach ( $this->_aFilter as $sKey => $sValue ) {
			if ($sKey == 'name') {
				$aWhere [] = 'use_name LIKE ?';
				$aValue [] = '%' . $sValue . '%';
			} elseif (is_array ( $sValue )) {
				$aWhere [] = 'use_' . $sKey . ' IN (?' . str_repeat ( ', ?', count ( $sValue ) - 1 ) . ')';
				$aValue = array_merge ( $aValue, $sValue );
			} else {
				$aWhere [] = 'use_' . $sKey . ' = ?';
				$aValue [] = $sValue;
			}
		}
		$sSql = 'SELECT * FROM users WHERE ' . implode ( ' AND ', $aWhere );
		$sSql .= ' ORDER BY ' . $this->_sSortName . ' ' . $this->_sSortType;
		$aList = Base::$oBase->Db_getList ( $sSql, $aValue, $iPage, $iLimit );
		foreach ( $aList ['data'] as $iKey => $aRow ) {
			foreach ( $aRow as $sKey => $sRow ) {
				unset ( $aList ['data'] [$iKey] [$sKey] );
				$sKey = preg_replace ( '/^use_/', '', $sKey );
				$aList ['data'] [$iKey] [$sKey] = $sRow;
			}
			$aList ['data'] [$iKey] ['status_value'] = $this->_aStatus [$aList ['data'] [$iKey] ['status']];
		}
		return $aList;
	}
	
	public function setFilter($sName, $sValue) {
		if ($this->_aFilter === null) {
			$this->setDefaultFilter ();
		}
		if (is_array ( $sName ) && is_array ( $sValue )) {
			foreach ( $sName as $iKey => $sRow ) {
				$this->setFilter ( $sRow, $sValue [$iKey] );
			}
		} else {
			$this->_aFilter [$sName] = $sValue;
		}
	}
	
	public function setSort($sName, $sType) {
		if ($sName) {
			$this->_sSortName = 'use_' . $sName;
			if ($sType == 'desc') {
				$this->_sSortType = 'desc';
			} else {
				$this->_sSortType = 'asc';
			}
		}
	}
	
	public function add($aInfo) {
		if ($aInfo ['name'] == '') {
			return false;
		}
		$aUserInfo = $this->get ( $aInfo ['name'], false );
		if (is_array ( $aUserInfo )) {
			return false;
		}
		$aInfo ['create_time'] = time ();
		$aInfo ['password'] = $this->_str2password ( $aInfo ['password'] );
		$iUserId = Base::$oBase->Db_insert ( 'users', $aInfo );
		if ($iUserId) {
			$this->_replacePrivilege ( $iUserId, $aInfo ['privilege'] );
			$this->_replaceAuthorize ( $iUserId, $aInfo ['authorize'] );
		}
		return $iUserId;
	}
	
	public function edit($aInfo) {
		if ($aInfo ['name'] == '') {
			return false;
		}
		$aUserInfo = $this->get ( $aInfo ['name'], false );
		if (is_array ( $aUserInfo ) && $aInfo ['id'] != $aUserInfo ['id']) {
			return false;
		}
		Base::$oBase->Db_update ( 'users', $aInfo );
		$this->_replacePrivilege ( $aInfo ['id'], $aInfo ['privilege'] );
		$this->_replaceAuthorize ( $aInfo ['id'], $aInfo ['authorize'] );
		Base::$oBase->Cache_del ( $aInfo ['id'], 'user' );
		return true;
	}
	
	public function del($iUserId) {
		$sSql = 'DELETE FROM users WHERE use_id = ?';
		Base::$oBase->Db_exec ( $sSql, $iUserId );
	}
	
	public function changePassword($iUserId, $sPassword) {
		$sSql = 'UPDATE users
				SET
					use_password = ?
				WHERE
					use_id = ?';
		Base::$oBase->Db_exec ( $sSql, array ($this->_str2password ( $sPassword ), $iUserId ) );
		Base::$oBase->Cache_del ( $iUserId, 'user' );
	}
	
	private function _replacePrivilege($iUserId, $aPrivilege) {
		Base::$oBase->Db_del ( 'user_privileges', array ('use_id' => $iUserId ) );
		if (is_array ( $aPrivilege )) {
			foreach ( $aPrivilege as $iRow ) {
				Base::$oBase->Db_insert ( 'user_privileges', array ('use_id' => $iUserId, 'pri_id' => $iRow ) );
			}
		}
	}
	
	private function _replaceAuthorize($iUserId, $aPrivilege) {
		Base::$oBase->Db_del ( 'authorize', array ('use_id' => $iUserId ) );
		if (is_array ( $aPrivilege )) {
			foreach ( $aPrivilege as $iRow ) {
				Base::$oBase->Db_insert ( 'authorize', array ('use_id' => $iUserId, 'pri_id' => $iRow ) );
			}
		}
	}
	
	public function encodePassword($sString) {
		return $this->_str2password ( $sString );
	}
}